/**
 * This software is copyrighted by Bosch Connected Devices and Solutions GmbH, 2016.
 * The use of this software is subject to the XDK SDK EULA
 */

/* system header files */
#include "BCDS_Basics.h"

/* own header files */
#include "BCDS_Gyroscope.h"
#include "Gyroscope.h"

/* additional interface header files */
#include "BCDS_Bmg160Utils.h"
#include <bmi160.h>
#include <bmg160.h>
#include "BCDS_Bmi160Utils.h"

/* local variables ********************************************************** */
/*  This variable is used to store the current value of range, it will be
 *  used to calculate the value range for BMG160 and BMI160. */
static uint16_t bmgRangeValue = BMG160SUPPORT_2000S_RANGE;
static uint16_t bmiRangeValue = BMI160SUPPORT_2000S_RANGE;

/* global variables ********************************************************* */
static const uint8_t bwLookUpTable[GYROSCOPE_BANDWIDTH_OUT_OF_RANGE] =
{
    UINT8_C(C_BMG160_BW_12HZ_U8X),
    UINT8_C(C_BMG160_BW_23HZ_U8X),
    UINT8_C(C_BMG160_BW_32HZ_U8X),
    UINT8_C(C_BMG160_BW_47HZ_U8X),
    UINT8_C(C_BMG160_BW_64HZ_U8X),
    UINT8_C(C_BMG160_BW_116HZ_U8X),
    UINT8_C(C_BMG160_BW_230HZ_U8X),
    UINT8_C(C_BMG160_NO_FILTER_U8X),
    UINT8_C(BCDS_BMI160_GYRO_OUTPUT_DATA_RATE_25HZ),
    UINT8_C(BCDS_BMI160_GYRO_OUTPUT_DATA_RATE_50HZ),
    UINT8_C(BCDS_BMI160_GYRO_OUTPUT_DATA_RATE_100HZ),
    UINT8_C(BCDS_BMI160_GYRO_OUTPUT_DATA_RATE_200HZ),
    UINT8_C(BCDS_BMI160_GYRO_OUTPUT_DATA_RATE_400HZ),
    UINT8_C(BCDS_BMI160_GYRO_OUTPUT_DATA_RATE_800HZ),
    UINT8_C(BCDS_BMI160_GYRO_OUTPUT_DATA_RATE_1600HZ),
    UINT8_C(BCDS_BMI160_GYRO_OUTPUT_DATA_RATE_3200HZ)
};

static const uint8_t modeLookUpTable[GYROSCOPE_POWERMODE_OUT_OF_RANGE] =
{
    UINT8_C(BMG160_MODE_NORMAL),
    UINT8_C(BMG160_MODE_DEEPSUSPEND),
    UINT8_C(BMG160_MODE_SUSPEND),
    UINT8_C(BMG160_MODE_FASTPOWERUP),
    UINT8_C(BMG160_MODE_ADVANCEDPOWERSAVING),
    UINT8_C(GYRO_MODE_NORMAL),
    UINT8_C(GYRO_MODE_FASTSTARTUP),
    UINT8_C(GYRO_MODE_SUSPEND)
};

static const uint8_t rangeLookUpTable[GYROSCOPE_OUT_OF_RANGE] =
{
    UINT8_C(BMG160SUPPORT_BSTLIB_125S_RANGE),
    UINT8_C(BMG160SUPPORT_BSTLIB_250S_RANGE),
    UINT8_C(BMG160SUPPORT_BSTLIB_500S_RANGE),
    UINT8_C(BMG160SUPPORT_BSTLIB_1000S_RANGE),
    UINT8_C(BMG160SUPPORT_BSTLIB_2000S_RANGE),
    UINT8_C(BCDS_BMI160_GYRO_RANGE_125_DEG_SEC),
    UINT8_C(BCDS_BMI160_GYRO_RANGE_250_DEG_SEC),
    UINT8_C(BCDS_BMI160_GYRO_RANGE_500_DEG_SEC),
    UINT8_C(BCDS_BMI160_GYRO_RANGE_1000_DEG_SEC),
    UINT8_C(BCDS_BMI160_GYRO_RANGE_2000_DEG_SEC),

};

static const uint8_t autoSleepDurationValueLookUpTable[GYROSCOPE_BMG160_AUTOSLEEP_DURATION_OUT_OF_RANGE] =
{
    UINT8_C(BCDS_BMG160_NO_AUTO_SLEEP_DURN_U8X),
    UINT8_C(BCDS_BMG160_4MS_AUTO_SLEEP_DURN_U8X),
    UINT8_C(BCDS_BMG160_5MS_AUTO_SLEEP_DURN_U8X),
    UINT8_C(BCDS_BMG160_8MS_AUTO_SLEEP_DURN_U8X),
    UINT8_C(BCDS_BMG160_10MS_AUTO_SLEEP_DURN_U8X),
    UINT8_C(BCDS_BMG160_15MS_AUTO_SLEEP_DURN_U8X),
    UINT8_C(BCDS_BMG160_20MS_AUTO_SLEEP_DURN_U8X),
    UINT8_C(BCDS_BMG160_40MS_AUTO_SLEEP_DURN_U8X)
};


static const uint8_t getModeLookUpTable[GYROSCOPE_POWERMODE_OUT_OF_RANGE] =
{
    UINT8_C(BMG160_MODE_NORMAL),
    UINT8_C(BMG160_MODE_DEEPSUSPEND),
    UINT8_C(BMG160_MODE_SUSPEND),
    UINT8_C(BMG160_MODE_FASTPOWERUP),
    UINT8_C(BMG160_MODE_ADVANCEDPOWERSAVING),
    UINT8_C(BCDS_BMI160_GYRO_MODE_SUSPEND),
    UINT8_C(BCDS_BMI160_GYRO_MODE_NORMAL),
    UINT8_C(BCDS_BMI160_GYRO_MODE_FASTSTARTUP)
};

static const uint16_t rangeValueLookUpTable[GYROSCOPE_OUT_OF_RANGE] = {
    UINT16_C(BMG160SUPPORT_125S_RANGE),
    UINT16_C(BMG160SUPPORT_250S_RANGE),
    UINT16_C(BMG160SUPPORT_500S_RANGE),
    UINT16_C(BMG160SUPPORT_1000S_RANGE),
    UINT16_C(BMG160SUPPORT_2000S_RANGE),
    UINT16_C(BMI160SUPPORT_125S_RANGE),
    UINT16_C(BMI160SUPPORT_250S_RANGE),
    UINT16_C(BMI160SUPPORT_500S_RANGE),
    UINT16_C(BMI160SUPPORT_1000S_RANGE),
    UINT16_C(BMI160SUPPORT_2000S_RANGE)
};

static const uint8_t sleepDurationValueLookUpTable[GYROSCOPE_BMG160_SLEEP_DURATION_OUT_OF_RANGE] = {
    UINT8_C(C_BMG160_NO_SLEEP_DURN_U8X),
    UINT8_C(C_BMG160_4MS_SLEEP_DURN_U8X),
    UINT8_C(C_BMG160_5MS_SLEEP_DURN_U8X),
    UINT8_C(C_BMG160_8MS_SLEEP_DURN_U8X),
    UINT8_C(C_BMG160_10MS_SLEEP_DURN_U8X),
    UINT8_C(C_BMG160_15MS_SLEEP_DURN_U8X),
    UINT8_C(C_BMG160_20MS_SLEEP_DURN_U8X)
};

/* inline functions ********************************************************* */
static int8_t mappingEnumForGetFunctions(uint8_t start, uint8_t end, uint8_t getValueToBeTransalated, const uint8_t * lookUpTablePtr)
{
    uint8_t i = UINT8_C(0);
    int8_t apiReturnValue = GET_MAPPING_ERROR;
    for (i = start; i <= end; i++)
    {
        if (getValueToBeTransalated == *(lookUpTablePtr + i))
        {
            apiReturnValue = i;
            break;
        }
    }
    return (apiReturnValue);
}

/* local functions ********************************************************** */
/**
 * @brief       This function maps error codes returned from BMG160 library to retcode values
 *
 * @param [in]  BMG160_RETURN_FUNCTION_TYPE Return value from BMG160 library
 *
 * @retval      RETCODE_OK              BMG160 sensor API call success
 * @retval      RETCODE_FAILURE         BMG160 sensor API call failed
 * @retval      RETCODE_INVALID_PARAM   BMG160 sensor API call failed because of invalid input parameter
 */
static Retcode_T bmg160LibErrorMapping(BMG160_RETURN_FUNCTION_TYPE BMG160_libReturn)
{
    Retcode_T returnValue = (Retcode_T) RETCODE_FAILURE;

    if (BMG160_libReturn == (BMG160_RETURN_FUNCTION_TYPE) UINT8_C(0))
    {
        returnValue = RETCODE_OK;
    }
    else if (BMG160_libReturn == E_BMG160_NULL_PTR)
    {
        returnValue = (Retcode_T) RETCODE_INVALID_PARAM;
    }
    else
    {
        returnValue = (Retcode_T) RETCODE_FAILURE;
    }

    return (returnValue);
}

/**
 * @brief       This function maps error codes returned from BMI160 library to retcode values
 *
 * @param [in]  BMI160_RETURN_FUNCTION_TYPE Return value from BMI160 library
 *
 * @retval      RETCODE_OK              BMI160 sensor API call success
 * @retval      RETCODE_FAILURE         BMI160 sensor API call failed
 */
static Retcode_T BMI160_libErrorMapping(BMI160_RETURN_FUNCTION_TYPE BMI160_libReturn)
{
    Retcode_T returnValue = (Retcode_T) RETCODE_FAILURE;

    if (BMI160_libReturn == SUCCESS)
    {
        returnValue = (Retcode_T) RETCODE_SUCCESS;
    }
    else if (BMI160_libReturn == E_BMI160_NULL_PTR)
    {
        returnValue = (Retcode_T) RETCODE_INVALID_PARAM;
    }
    else
    {
        returnValue = (Retcode_T) RETCODE_FAILURE;
    }

    return (returnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_init(Gyroscope_HandlePtr_T handle)
{
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;

    if ((NULL == handle) || (NULL == handle->sensorPtr))
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (true == handle->sensorInfo.initializationStatus)
    {
        return (RETCODE_OK);
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:
        apiReturnValue = Bmg160Utils_initialize((Bmg160Utils_InfoPtr_T) handle->sensorPtr);
        if (RETCODE_OK == apiReturnValue)
        {
            handle->sensorInfo.initializationStatus = true;
        }
        else
        {
            handle->sensorInfo.initializationStatus = false;
        }
        break;
    case BMI160_GYRO_SENSOR:
        apiReturnValue = Bmi160Utils_initialize((Bmi160Utils_InfoPtr_T) handle->sensorPtr);
        if (RETCODE_OK == apiReturnValue)
        {
            handle->sensorInfo.initializationStatus = true;
        }
        else
        {
            handle->sensorInfo.initializationStatus = false;
        }
        break;
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_setBandwidth(Gyroscope_HandlePtr_T handle, Gyroscope_Bandwidth_T bandwidth)
{
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;
    BMI160_RETURN_FUNCTION_TYPE bmiLibReturn = INT8_C(-1);

    if ((NULL == handle) || (NULL == handle->sensorPtr))
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }

    if ((bandwidth >= GYROSCOPE_BANDWIDTH_OUT_OF_RANGE))
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_INVALID_PARAM));
    }

    if (false == (handle->sensorInfo.initializationStatus))
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:
        if (bandwidth > GYROSCOPE_BMG160_BANDWIDTH_523HZ )
        {
            apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
        }
        else
        {
            bmgLibReturn = bmg160_set_high_bw(FILTERED_LOW_BANDWIDTH);
            if (C_BMG160_SUCCESS == bmgLibReturn)
            {
                bmgLibReturn = bmg160_set_bw(bwLookUpTable[bandwidth]);
            }
            apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        }
        break;
    case BMI160_GYRO_SENSOR:
        if (bandwidth < GYROSCOPE_BMI160_BANDWIDTH_10_7HZ)
        {
            apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
        }
        else
        {
            bmiLibReturn = bmi160_set_gyro_bw(FILTERED_LOW_BANDWIDTH);

            if (SUCCESS == bmiLibReturn)
            {
                bmiLibReturn = bmi160_set_gyro_output_data_rate(bwLookUpTable[bandwidth]);
            }
            apiReturnValue = BMI160_libErrorMapping(bmiLibReturn);
        }
        break;
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_setRange(Gyroscope_HandlePtr_T handle, Gyroscope_Range_T range)
{
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;
    BMI160_RETURN_FUNCTION_TYPE bmiLibReturn = INT8_C(-1);

    if (NULL == handle)
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (range >= GYROSCOPE_OUT_OF_RANGE)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (handle->sensorInfo.initializationStatus == false)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:
        if (GYROSCOPE_BMG160_RANGE_2000s < range)
        {
            apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
        }
        else
        {
            bmgLibReturn = bmg160_set_range_reg(rangeLookUpTable[range]);
            if (C_BMG160_SUCCESS == bmgLibReturn)
            {
                bmgRangeValue = rangeValueLookUpTable[range];
            }

            apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        }
        break;
    case BMI160_GYRO_SENSOR:
        if (GYROSCOPE_BMI160_125S_RANGE > range)
        {
            apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
        }
        else
        {
            bmiLibReturn = bmi160_set_gyro_range(rangeLookUpTable[range]);

            if (SUCCESS == bmiLibReturn)
            {
                bmiRangeValue = rangeValueLookUpTable[range];
            }

            apiReturnValue = BMI160_libErrorMapping(bmiLibReturn);
        }
        break;
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_getRange(Gyroscope_HandlePtr_T handle, Gyroscope_RangePtr_T range)
{

    int8_t tempretVal = GET_MAPPING_ERROR;
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;
    BMI160_RETURN_FUNCTION_TYPE bmiLibReturn = INT8_C(-1);

    if (NULL == handle || NULL == range)
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }

    if (handle->sensorInfo.initializationStatus == false)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:
        bmgLibReturn = bmg160_get_range_reg((uint8_t *) range);
        apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        if (RETCODE_OK == apiReturnValue)
        {
            tempretVal = mappingEnumForGetFunctions((uint8_t) GYROSCOPE_BMG160_RANGE_125s, (uint8_t) GYROSCOPE_BMG160_RANGE_2000s, (uint8_t) *range, rangeLookUpTable);
            if (tempretVal != GET_MAPPING_ERROR)
            {
                *range = (Gyroscope_Range_T) tempretVal;
            }
            else
            {
                apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
            }
        }
        break;
    case BMI160_GYRO_SENSOR:

        bmiLibReturn = bmi160_get_gyro_range((uint8_t *) range);

        apiReturnValue = bmg160LibErrorMapping(bmiLibReturn);
        if (RETCODE_OK == apiReturnValue)
        {
            tempretVal = mappingEnumForGetFunctions((uint8_t) GYROSCOPE_BMI160_125S_RANGE, (uint8_t) GYROSCOPE_BMI160_2000S_RANGE, (uint8_t) *range, rangeLookUpTable);
            if (tempretVal != GET_MAPPING_ERROR)
            {
                *range = (Gyroscope_Range_T) tempretVal;
            }
            else
            {
                apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
            }
        }
        break;
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_getBandwidth(Gyroscope_HandlePtr_T handle, Gyroscope_BandwidthPtr_T bandwidth)
{
    int8_t tempretVal = GET_MAPPING_ERROR;
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    Gyroscope_Bandwidth_T tempBandwidth = GYROSCOPE_BANDWIDTH_OUT_OF_RANGE;
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;
    BMI160_RETURN_FUNCTION_TYPE bmiLibReturn = INT8_C(-1);

    if ((NULL == handle) || ( NULL == bandwidth))
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (handle->sensorInfo.initializationStatus == false)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:
        bmgLibReturn = bmg160_get_bw((uint8_t *) bandwidth);
        apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        if (RETCODE_OK == apiReturnValue)
        {
            tempBandwidth = *bandwidth;
            tempretVal = mappingEnumForGetFunctions((uint8_t) GYROSCOPE_BMG160_BANDWIDTH_12HZ, (uint8_t) GYROSCOPE_BMG160_BANDWIDTH_523HZ, (uint8_t) tempBandwidth, bwLookUpTable);
            if (tempretVal != GET_MAPPING_ERROR)
            {
                *bandwidth = (Gyroscope_Bandwidth_T) tempretVal;
            }
            else
            {
                apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
            }
        }
        break;
    case BMI160_GYRO_SENSOR:

        bmiLibReturn = bmi160_get_gyro_output_data_rate((uint8_t *) bandwidth);

        apiReturnValue = bmg160LibErrorMapping(bmiLibReturn);
        if (RETCODE_OK == apiReturnValue)
        {
            tempBandwidth = *bandwidth;
            tempretVal = mappingEnumForGetFunctions((uint8_t) GYROSCOPE_BMI160_BANDWIDTH_10_7HZ, (uint8_t) GYROSCOPE_BMI160_BANDWIDTH_890HZ, (uint8_t) tempBandwidth, bwLookUpTable);
            if (tempretVal != GET_MAPPING_ERROR)
            {
                *bandwidth = (Gyroscope_Bandwidth_T) tempretVal;
            }
            else
            {
                apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
            }
        }
        break;
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_setMode(Gyroscope_HandlePtr_T handle, Gyroscope_Powermode_T powermode)
{
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;
    BMI160_RETURN_FUNCTION_TYPE bmiLibReturn = INT8_C(-1);

    if ((NULL == handle) || (NULL == handle->sensorPtr))
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (powermode >= GYROSCOPE_POWERMODE_OUT_OF_RANGE)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (false == handle->sensorInfo.initializationStatus)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:
        if (powermode > GYROSCOPE_BMG160_POWERMODE_ADVANCE_POWERUP)
        {
            apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
        }
        else
        {
            bmgLibReturn = bmg160_set_power_mode(modeLookUpTable[powermode]);
            apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        }
        break;
    case BMI160_GYRO_SENSOR:
        if ((powermode < GYROSCOPE_BMI160_POWERMODE_NORMAL) || (powermode > GYROSCOPE_BMI160_POWERMODE_SUSPEND))
        {
            apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
        }
        else
        {
            bmiLibReturn = bmi160_set_command_register(modeLookUpTable[powermode]);
            apiReturnValue = BMI160_libErrorMapping(bmiLibReturn);
        }
        break;
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_getMode(Gyroscope_HandlePtr_T handle, Gyroscope_PowermodePtr_T powermode)
{
    int8_t tempretVal = GET_MAPPING_ERROR;
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;
    BMI160_RETURN_FUNCTION_TYPE bmiLibReturn = INT8_C(-1);

    if ((NULL == handle) || (NULL == powermode))
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (INIT_NOT_DONE == handle->sensorInfo.initializationStatus)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:

        bmgLibReturn = bmg160_get_power_mode((uint8_t *) powermode);

        apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        if (RETCODE_OK == apiReturnValue)
        {
            tempretVal = mappingEnumForGetFunctions((uint8_t) GYROSCOPE_BMG160_POWERMODE_NORMAL, (uint8_t) GYROSCOPE_BMG160_POWERMODE_ADVANCE_POWERUP, (uint8_t) *powermode, modeLookUpTable);
            if (tempretVal != GET_MAPPING_ERROR)
            {
                *powermode = (Gyroscope_Powermode_T) tempretVal;
            }
            else
            {
                apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
            }
        }
        break;
    case BMI160_GYRO_SENSOR:

        bmiLibReturn = bmi160_get_gyro_power_mode_stat((uint8_t *) powermode);

        apiReturnValue = BMI160_libErrorMapping(bmiLibReturn);
        if (RETCODE_OK == apiReturnValue)
        {
            tempretVal = mappingEnumForGetFunctions((uint8_t) GYROSCOPE_BMI160_POWERMODE_NORMAL, (uint8_t) GYROSCOPE_BMI160_POWERMODE_SUSPEND, (uint8_t) *powermode, getModeLookUpTable);
            if (tempretVal != GET_MAPPING_ERROR)
            {
                *powermode = (Gyroscope_Powermode_T) tempretVal;
            }
            else
            {
                apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
            }
        }
        break;
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_readXyzValue(Gyroscope_HandlePtr_T handle, Gyroscope_XyzDataPtr_T gyrodata)
{
    struct bmi160_gyro_t bmiGyroData =
    {   INT16_C(0), INT16_C(0), INT16_C(0)};

    struct bmg160_data_t bmgGyroData = { INT16_C(0), INT16_C(0), INT16_C(0), { INT8_C(0) } };
    AxisRemap_Data_T readDataGyro = { INT32_C(0), INT32_C(0), INT32_C(0) };
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;
    BMI160_RETURN_FUNCTION_TYPE bmiLibReturn = INT8_C(-1);

    if ((NULL == handle) || ( NULL == handle->sensorPtr) || (NULL == gyrodata))
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (INIT_NOT_DONE == handle->sensorInfo.initializationStatus)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:

        bmgLibReturn = bmg160_get_data_XYZ(&bmgGyroData);

        apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        if (RETCODE_OK == apiReturnValue)
        {
            readDataGyro.x = bmgGyroData.datax;
            readDataGyro.y = bmgGyroData.datay;
            readDataGyro.z = bmgGyroData.dataz;
            apiReturnValue = Bmg160Utils_remapAxis((Bmg160Utils_InfoPtr_T) handle->sensorPtr, &readDataGyro);
        }
        if (RETCODE_OK == apiReturnValue)
        {
            gyrodata->xAxisData = readDataGyro.x;
            gyrodata->yAxisData = readDataGyro.y;
            gyrodata->zAxisData = readDataGyro.z;
        }
        break;
    case BMI160_GYRO_SENSOR:
        bmiLibReturn = bmi160_read_gyro_xyz(&bmiGyroData);
        apiReturnValue = BMI160_libErrorMapping(bmiLibReturn);
        if (RETCODE_OK == apiReturnValue)
        {
            readDataGyro.x = bmiGyroData.x;
            readDataGyro.y = bmiGyroData.y;
            readDataGyro.z = bmiGyroData.z;
            apiReturnValue = Bmi160Utils_remapAxis((Bmi160Utils_InfoPtr_T) handle->sensorPtr, &readDataGyro);
        }
        if (RETCODE_OK == apiReturnValue)
        {
            gyrodata->xAxisData = readDataGyro.x;
            gyrodata->yAxisData = readDataGyro.y;
            gyrodata->zAxisData = readDataGyro.z;
        }
        break;
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_readXyzDegreeValue(Gyroscope_HandlePtr_T handle, Gyroscope_XyzDataPtr_T gyrodata)
{
    struct bmi160_gyro_t bmiGyroData =
    {   INT16_C(0), INT16_C(0), INT16_C(0)};
    AxisRemap_Data_T readDataGyro = { INT32_C(0), INT32_C(0), INT32_C(0) };
    struct bmg160_data_t bmgGyroData = { INT16_C(0), INT16_C(0), INT16_C(0), {INT8_C(0)} };
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    int64_t bmgConvertionData = INT64_C(0);
    int64_t bmiConvertionData = INT64_C(0);
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;
    BMI160_RETURN_FUNCTION_TYPE bmiLibReturn = INT8_C(-1);

    if ((NULL == handle) || (NULL == gyrodata))
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (INIT_NOT_DONE == handle->sensorInfo.initializationStatus)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:

        bmgLibReturn = bmg160_get_data_XYZ(&bmgGyroData);
        apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        if (RETCODE_OK == apiReturnValue)
        {
            bmgConvertionData = ((BMG160S_GYRO_CONVERSION_FACTOR) * (int64_t) (bmgRangeValue) * (bmgGyroData.datax));
            readDataGyro.x = (bmgConvertionData / (BMG160S_GYRO_ONEBITRESOLUTION));

            bmgConvertionData = ((BMG160S_GYRO_CONVERSION_FACTOR) * (int64_t) (bmgRangeValue) * (bmgGyroData.datay));
            readDataGyro.y = (bmgConvertionData / BMG160S_GYRO_ONEBITRESOLUTION);

            bmgConvertionData = ((BMG160S_GYRO_CONVERSION_FACTOR) * (int64_t) (bmgRangeValue) * (bmgGyroData.dataz));
            readDataGyro.z = (bmgConvertionData / BMG160S_GYRO_ONEBITRESOLUTION);

            apiReturnValue = Bmg160Utils_remapAxis((Bmg160Utils_InfoPtr_T) handle->sensorPtr, &readDataGyro);
        }
        if (RETCODE_OK == apiReturnValue)
        {
            gyrodata->xAxisData = readDataGyro.x;
            gyrodata->yAxisData = readDataGyro.y;
            gyrodata->zAxisData = readDataGyro.z;
        }
        break;
    case BMI160_GYRO_SENSOR:
        {
            bmiLibReturn = bmi160_read_gyro_xyz(&bmiGyroData);
            apiReturnValue = BMI160_libErrorMapping(bmiLibReturn);
            if (RETCODE_OK == apiReturnValue)
            {
                bmiConvertionData = ((BMI160S_GYRO_CONVERSION_FACTOR) * (int64_t) (bmiRangeValue) * (bmiGyroData.x));
                readDataGyro.x = (bmiConvertionData / (BMI160S_GYRO_ONEBITRESOLUTION));

                bmiConvertionData = ((BMI160S_GYRO_CONVERSION_FACTOR) * (int64_t) (bmiRangeValue) * (bmiGyroData.y));
                readDataGyro.y = (bmiConvertionData / BMI160S_GYRO_ONEBITRESOLUTION);

                bmiConvertionData = ((BMI160S_GYRO_CONVERSION_FACTOR) * (int64_t) (bmiRangeValue) * (bmiGyroData.z));
                readDataGyro.z = (bmiConvertionData / BMI160S_GYRO_ONEBITRESOLUTION);

                apiReturnValue = Bmi160Utils_remapAxis((Bmi160Utils_InfoPtr_T) handle->sensorPtr, &readDataGyro);

            }
            if (RETCODE_OK == apiReturnValue)
            {

                gyrodata->xAxisData = readDataGyro.x;
                gyrodata->yAxisData = readDataGyro.y;
                gyrodata->zAxisData = readDataGyro.z;
            }
            break;
        }
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_setSleepDuration(Gyroscope_HandlePtr_T handle, Gyroscope_SleepDuration_T lowPowerModeSleepDuration)
{
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;

    if ((NULL == handle) || (NULL == handle->sensorPtr))
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (lowPowerModeSleepDuration >= GYROSCOPE_BMG160_SLEEP_DURATION_OUT_OF_RANGE)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (false == handle->sensorInfo.initializationStatus)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:

        bmgLibReturn = bmg160_set_sleep_durn(sleepDurationValueLookUpTable[lowPowerModeSleepDuration]);

        apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        break;

    case BMI160_GYRO_SENSOR:
        apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
        break;

    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }
    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_setAutoSleepDuration(Gyroscope_HandlePtr_T handle, Gyroscope_AutoSleepDuration_T lowPowerModeSleepDuration,Gyroscope_Bandwidth_T bandwidthForAutoSleep)
{
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    BMG160_RETURN_FUNCTION_TYPE bmgLibReturn = C_BMG160_FAILURE;

    if ((NULL == handle) || (NULL == handle->sensorPtr))
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (bandwidthForAutoSleep > GYROSCOPE_BMG160_BANDWIDTH_523HZ)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_INVALID_PARAM));
    }

    if (lowPowerModeSleepDuration >= GYROSCOPE_BMG160_AUTOSLEEP_DURATION_OUT_OF_RANGE)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (INIT_NOT_DONE == handle->sensorInfo.initializationStatus)
    {
        return (RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) RETCODE_UNINITIALIZED));
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:

        bmgLibReturn = bmg160_set_auto_sleep_durn(autoSleepDurationValueLookUpTable[lowPowerModeSleepDuration], (uint8_t)bandwidthForAutoSleep);
        apiReturnValue = bmg160LibErrorMapping(bmgLibReturn);
        break;

    case BMI160_GYRO_SENSOR:
        apiReturnValue = (Retcode_T) RETCODE_NOT_SUPPORTED;
        break;

    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}

/* API documentation is in public interface header file 'BCDS_Gyroscope.h' */
Retcode_T Gyroscope_deInit(Gyroscope_HandlePtr_T handle)
{
    Retcode_T apiReturnValue = (Retcode_T) RETCODE_FAILURE;
    if (NULL == handle)
    {
        return (RETCODE(RETCODE_SEVERITY_FATAL, (uint32_t) RETCODE_INVALID_PARAM));
    }
    if (INIT_NOT_DONE == handle->sensorInfo.initializationStatus)
    {
        return (RETCODE_OK);
    }

    switch (handle->sensorInfo.sensorID)
    {
    case BMG160_GYRO_SENSOR:
        {
            apiReturnValue = Bmg160Utils_uninitialize((Bmg160Utils_InfoPtr_T) handle->sensorPtr);
            handle->sensorInfo.initializationStatus = INIT_NOT_DONE;
            break;
        }
    case BMI160_GYRO_SENSOR:
        {
            apiReturnValue = Bmi160Utils_uninitialize((Bmi160Utils_InfoPtr_T) handle->sensorPtr);
            handle->sensorInfo.initializationStatus = INIT_NOT_DONE;
            break;
        }
    default:
        apiReturnValue = (Retcode_T) RETCODE_INVALID_PARAM;
        break;
    }

    if ((RETCODE_OK != apiReturnValue) && (Retcode_getPackage(apiReturnValue) == PACKAGE_ID_DEFAULT))
    {
        apiReturnValue = RETCODE(RETCODE_SEVERITY_ERROR, (uint32_t) apiReturnValue);
    }

    return (apiReturnValue);
}
